// songrenderer.cpp

// 2008-05-01 17:59:56 (Jake): created

#include "crankit_precompiled.h"

#include "songrenderer.h"
#include "game.h"

SongRendererUpdater::SongRendererUpdater(SongRenderer* songRenderer) :
	_songRenderer(songRenderer)
{

}

void SongRendererUpdater::operator()(osg::Node* node, osg::NodeVisitor* nv)
{
	Game* game = _songRenderer->getGame();

	// TODO: this should not be here, and simulation time should be used instead
	double t = osg::Timer::instance()->time_s();
	game->setTime(t);		

	Song* currentSong = game->getSong();
	if (currentSong != 0) {
		float bpm = currentSong->getBaseBPM();
		float velocity = bpm/20;
		float time = game->getTime();
		float posy = -time * velocity;

		osg::PositionAttitudeTransform* pat = dynamic_cast<osg::PositionAttitudeTransform*>(node);
		pat->setPosition(osg::Vec3(0, posy, 0));

		/*
		osg::Vec3 center(0, pos, 0);
		osg::Vec3 eye(0, pos, 0.8);
		osg::Vec3 up(0, 0, 1);
		_matrix = osg::Matrixd::lookAt(eye, center, up);

		_eye = eye;
		_rotation.makeRotate(-30, osg::Vec3(1, 0, 0));
		*/
	}
	
	traverse(node, nv);
}

SongRenderer::SongRenderer(Game* game) : _game(game)
{
	_bandSize = 0.25f;
//	_timeSize = 0.001f;
	_timeSize = 0.01f;
}

osg::Node* SongRenderer::renderBars()
{
	osg::Group* barsNode = new osg::Group();

	/*
	const SongNotes& notes = song.getNotes();
	const SongNote& lastNote = notes.back();
	*/

	osg::Geode* geode = new osg::Geode();
	osg::Vec3 center(0, 0, -0.1);
	osg::Shape* shape = new osg::Box(center, _bandSize*7, 0.2, 0.2);
	osg::ShapeDrawable* drawable = new osg::ShapeDrawable(shape);
	drawable->setColor(osg::Vec4(0, 1, 1, 1));
	geode->addDrawable(drawable);
	barsNode->addChild(geode);
	
	_barsNode = barsNode;

	return _barsNode.get();
}

osg::Node* SongRenderer::renderNote(const SongNote& note)
{
	float bandOffset = -_bandSize * 5 / 2;
	float height = 0.2f;
	float radius = 0.05f;
	osg::Vec3 center(note.band * _bandSize + bandOffset, note.time * _timeSize, height/3);

	osg::Geode* geode = new osg::Geode();
	osg::Shape* shape = new osg::Cone(center, radius, height);
	osg::ShapeDrawable* drawable = new osg::ShapeDrawable(shape);
	drawable->setColor(osg::Vec4(1, 1, 0, 1));
	geode->addDrawable(drawable);

	return geode;
}

osg::Node* SongRenderer::renderNotes()
{
	osg::ref_ptr<osg::PositionAttitudeTransform> root = new osg::PositionAttitudeTransform();
	root->setDataVariance(osg::Object::DYNAMIC);
	Song* song = _game->getSong();
	int level = _game->getLevel();

	const SongNotes& notes = song->getNotes();
	for (SongNotes::const_iterator iter = notes.begin(); 
		iter != notes.end();
		++iter)
	{
		const SongNote& note = *iter;

		if (note.level == level) {
			osg::ref_ptr<osg::Node> noteNode = renderNote(note);
			root->addChild(noteNode.get());
		}
	}

	_notesNode = root.get();

	_notesNode->setUpdateCallback(new SongRendererUpdater(this));

	return _notesNode.get();
}
